/*
 * song definitions
 *
 * Choi Jonghwan <saxboy@gmail.com>
 * 2006/04/22
 */

/* 
 * TODO:
 *
 * - add repetitions
 * - do not limit the length of a song
 */

#ifndef __SONG_H__
#define __SONG_H__

#include "chord.h"
#include "instrument.h"

/* FIXME: use list here... */
#define MAX_BEATS_PER_BAR	8
#define MAX_BARS_PER_SONG	32
#define MAX_VOICES_PER_SONG	6
#define MAX_EVENTS_PER_VOICE (MAX_BEATS_PER_BAR * MAX_BARS_PER_SONG * 32)

typedef struct __BAR {

	/* measure definition */
	int measure_count; 
	int measure_base; 

	/* chord definitions */
	int chord_count; 
	struct __chord_storage {
		CHORD chord; 
		int beat_length; 
		int b_same_as_prev_chord; 
	} chords[MAX_BEATS_PER_BAR]; 

	/* what else? */

} _BAR; 
typedef _BAR *BAR; 

BAR bar_New(void); 
BAR bar_NewFromString(const char *barstr); 
int bar_Delete(BAR b); 
int bar_SetMeasure(BAR b, int count, int base); 
//int bar_AddChord(BAR b, CHORD c, int beat); 
int bar_SetChord(BAR b, CHORD c, int beat, int b_same_as_prev); 
int bar_GetChordCount(BAR b); 
CHORD bar_GetChord(BAR b, int beat); 
int bar_ImportString(BAR b, const char *str); 


/* voice:
 *
 * rendered note list for each voice, 
 * each artist may have multiple voices (eg. piano, guitar)
 */
typedef enum __voice_event {
	VOICE_EVENT_NOTE=0, 
	VOICE_EVENT_BAR_START=0x8000, 
	VOICE_EVENT_BAR_END=0x4000, 
	/* FIXME: somethin' else? */
} VOICE_EVENT; 

typedef struct __voice {
	
	INSTRUMENT instrument;	/* instrument */

	/* list of voice events */
	int event_count;
	VOICE_EVENT events[MAX_EVENTS_PER_VOICE]; 

	/* list of notes */
	int notes_count; 
	NOTE notes[MAX_EVENTS_PER_VOICE]; 

	/* FIXME: need general way to solve it */

	/* drum pattern : only for drummers */
	int b_is_drummer; 
	char drum_pattern[128]; 


	/* chord voicing */
	int b_is_chord_voicing;




	/* FIXME:
	 *
	 * we cannot model phrases like CD[EC]C[EC]C 
	 *
	 * use instrument, voice type instead b_is_drummer
	 */


} _VOICE; 
typedef _VOICE *VOICE; 

VOICE voice_New(void); 
int voice_Delete(VOICE v); 
int voice_AddEvent(VOICE v, VOICE_EVENT e, NOTE n); 

/*
 * song:
 *
 * song object
 */
typedef struct __SONG {

	/* measure definition */
	int measure_count; 
	int measure_base; 

	/* bars, used only for abstract musical structure */
	int bar_count; 
	BAR bars[MAX_BARS_PER_SONG]; 

	/* voices, each voice has real rendered notes */
	int voice_count; 
	VOICE voices[MAX_VOICES_PER_SONG]; 
	
} _SONG; 
typedef _SONG *SONG; 

/* public song api's */

SONG song_New(void); 
int song_Delete(SONG s); 

int song_SetMeasure(SONG s, int count, int base); 
int song_AddBar(SONG s, BAR b); 
int song_Transpose(SONG s, int degree);
int song_Print(SONG s, FILE *fp); 
//int song_Export(SONG s, SONGSTYLE style, FILE *fp); 

int song_AddVoice(SONG s, VOICE v); 
int song_GetVoiceCount(SONG s); 
VOICE song_GetVoice(SONG s, int i); 

#endif /* __SONG_H__ */
